<template>
  <div>

    <h1>自定义指令的使用(局部指令 与 全局指令)</h1>
    <h3>1: v-loadmore 解决下拉框 下拉加载更多</h3>
    <!--    v-loadmore="expression"-->
    <el-select v-model="test"
               clearable
               v-loadmore="loadMore"
               :remote-method="remoteSearch"
               remote
               filterable
               placeholder="请选择版本"
               style="width: 200px"
               @change="listValueChange">
      <el-option
        v-for="item in List"
        :key="item.id"
        :label="item.name"
        :value="item.id"
      />
    </el-select>
    <h3>2: v-copy 简单版复制文本</h3>
    <div v-copy>hello world</div>

    <h3>3: v-el-drag-dialog 实现托拽模态框</h3>
    <el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button>

    <el-dialog
      v-el-drag-dialog
      title="提示"
      :visible.sync="dialogVisible"
      width="30%"
      :before-close="handleClose">
      <span>这是一段信息</span>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>

    <br>
    <h3>4: v-clipboard 实现文本复制</h3>
    <el-input v-model="inputData" placeholder="Please input" style="width:400px;max-width:100%;"/>
    <el-button v-clipboard:copy="inputData" v-clipboard:success="clipboardSuccess" type="primary"
               icon="el-icon-document">
      复制文本
    </el-button>

    <br>
    <h3>5: v-debounce 实现防抖</h3>
    <el-button v-debounce="debounceClick">防抖</el-button>
    <el-input style="width: 200px" v-model="inp" v-debounceInp="debounceChange"></el-input>
    <!-- 拖拽指令 什么都能拖 -->
    <div v-drags  style="width: 200px;height: 200px;background-color: red;">
        <div>1</div>
        <div>1</div>
        <div>1</div>
    </div>

    <h3>6: 图片预览指令</h3>
    <img :src="imgSrc" alt="xx" v-imgAlart>

    <hr>
    <h3>放大镜效果</h3>
    <div class="left">
      <img class="leftImg" :src="imgSrc2" alt="" />
      <!-- 鼠标层罩 -->
      <div v-show="topShow" class="top" :style="topStyle"></div>
      <!-- 最顶层覆盖了整个原图空间的透明层罩 -->
      <div
        class="maskTop"
        @mouseenter="enterHandler"
        @mousemove="moveHandler"
        @mouseout="outHandler"
      ></div>
    </div>
    <div v-show="rShow" class="right">
      <img
        :style="r_img"
        class="rightImg"
        :src="imgSrc2"
        alt=""
      />
    </div>
  </div>
</template>
<script>
  import Axios from 'axios'
  import copy from "../../common/directive/localDirective/copy/copy";
  import elDragDialog from "../../common/directive/localDirective/el-drag-dialog/drag";
  import clipboard from "../../common/directive/localDirective/clipboard";
  import imgAlart from "../../common/directive/localDirective/imgAlart/alart";

  export default {
    name: 'directive',
    components: {},
    data() {
      return {
        imgSrc:require("@/assets/flex常用.png"),
        imgSrc2:require("@/assets/404.png"),
        a: "xxx",
        test: "",
        List: [
          {id: 1, name: "wf1"},
          {id: 2, name: "wf2"},
          {id: 3, name: "wf3"},
          {id: 4, name: "wf4"},
          {id: 6, name: "wf5"},
          {id: 7, name: "wf5"},
          {id: 8, name: "wf5"},
          {id: 9, name: "wf5"},
          {id: 10, name: "wf5"},
          {id: 15, name: "wf5"},
          {id: 16, name: "c5"},
        ],
        dialogVisible: false,
        inputData: "待复制的文本信息",
        inp: "xxx",

        // 放大镜
        topStyle: { transform: "" },
        r_img: {},
        topShow: false,
        rShow: false,
      }
    },
    created() {

    },
    mounted() {

    },
    methods: {

      loadMore(val) {
        // console.log(val)
        console.log("loadMore加载更多") //
        // this.pageNum++
        // this.getList()

      },
      remoteSearch() {
        console.log("远程搜索")
      },

      listValueChange(val) {
        console.log("选中的值", val)
      },

      handleClose(done) {
        console.log("做一些事情")
        /* this.$confirm('确认关闭？')
           .then(_ => {

             done();
           })
           .catch(_ => {});*/
      },
      clipboardSuccess() {
        this.$message.success("复制成功")
      },
      debounceClick() {
        console.log("防抖")
      },
      debounceChange() {
        console.log(this.inp)
      },


      // 放大镜效果
      // 鼠标进入原图空间函数
      enterHandler() {
        // 层罩及放大空间的显示
        this.topShow = true;
        this.rShow = true;
      },
      // 鼠标移动函数
      moveHandler(event) {
        // 鼠标的坐标位置
        let x = event.offsetX;
        let y = event.offsetY;
        // 层罩的左上角坐标位置，并对其进行限制：无法超出原图区域左上角
        let topX = x - 100 < 0 ? 0 : x - 100;
        let topY = y - 100 < 0 ? 0 : y - 100;
        // 对层罩位置再一次限制，保证层罩只能在原图区域空间内
        if (topX > 200) {
          topX = 200;
        }
        if (topY > 200) {
          topY = 200;
        }
        // 通过 transform 进行移动控制
        this.topStyle.transform = `translate(${topX}px,${topY}px)`;
        this.r_img.transform = `translate(-${2*topX}px,-${2*topY}px)`; // 负号 是为了反方向移动，2 倍是移动距离的两倍
      },
      // 鼠标移出函数
      outHandler() {
        // 控制层罩与放大空间的隐藏
        this.topShow = false;
        this.rShow = false;
      }
    },
    // 局部指令的使用
    // 页面中自定义 或者 导进来
    directives: {
      'loadmore': {
        //只调用一次，指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
        bind(el, binding, vNode) {
          //  selectors表示一个或多个匹配元素的 CSS 选择器
          const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');
          SELECTWRAP_DOM.addEventListener('scroll', function () {
            /*
            * scrollHeight 获取元素内容高度(只读)
            * scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
            * clientHeight 读取元素的可见高度(只读)
            * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
            * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
            */

            // 这个 + 1 有妙用
            // 滚动区域总高度 - 滚动了多少 <= 可视区域
            // console.log(this.scrollHeight,this.scrollTop,this.clientHeight)
            const condition = this.scrollHeight - this.scrollTop <= this.clientHeight + 1
            if (condition) {
              console.log(binding)
              binding.value && binding.value(binding.arg) // binding.value() 需要绑定函数  arg 传参
            }
          });
        },
        // 被绑定元素插入父节点时调用 (仅保证父节点存在，但不一定已被插入文档中)。
        inserted(el, binding, vNode) {

        },
        // 所在组件的 VNode 更新时调用，但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变，也可能没有
        update(el, binding, vNode) {

        },
        // 解绑时
        unbind(el, binding, vNode) {

        }
      },
      "debounce": {
        bind(el, binding, vnode) {
          let timer = {}
          el.addEventListener('click', () => {
            if (timer) {
              clearTimeout(timer)
            }
            console.log(binding)
            timer = setTimeout(() => {
              binding.value(binding.arg)
              // binding.value() 需要绑定函数
            }, 2000)
          })

        },
        /*   update(el, binding, vnode) {

           },*/
        /*  componentUpdated(el, binding, vnode) {

          },*/
      },
      //
      "debounceInp": {
        bind(el, binding){
          let timer = {}
          el.addEventListener('input', () => {
            if (timer) {
              clearTimeout(timer)
            }
            console.log(binding)
            timer = setTimeout(() => {
              binding.value() //需要绑定函数
              clearTimeout(timer)
            }, 2000)
          })
          // binding.value(binding.arg)
        },
        inserted(){

        },
        /*为什么 update 会重复执行*/
        update(el, binding, vnode) {

     /*     let timer = {}
          el.addEventListener('input', () => {
            if (timer) {
              clearTimeout(timer)
            }

            console.log(binding)
            console.log(binding.value.length)
            timer = setTimeout(() => {

              binding.value(binding.arg)
              clearTimeout(timer)
            }, 2000)
          })*/
        },
      },
      copy,
      elDragDialog,
      clipboard,
      imgAlart,
       "drags": {
        //   el指令绑定的dom元素
        // inserted: function(el) {
        //   el.style.position = "absolute";
        //   // e对应事件对象
        //   el.onmousedown = e => {
        //     // 按下鼠标
        //     var ex = e.clientX - el.offsetLeft;
        //     var ey = e.clientY - el.offsetTop;
        //     el.onmousemove = e => {
        //       // 移动鼠标
        //       var ex1 = e.clientX - ex;
        //       var ey1 = e.clientY - ey;
        //       el.style.left = ex1 + "px";
        //       el.style.top = ey1 + "px";
        //     };
        //     el.onmouseup = e => {
        //       // 抬起鼠标
        //       el.onmousemove = null;
        //     };
        //   };
        // }
        inserted(obj,binding){
          obj.onmousedown = function(event){
            obj.style.position = "absolute";
            obj.style.cursor = "move"
            obj.setCapture && obj.setCapture();
            event = event || window.event;
            var ol = event.clientX - obj.offsetLeft;
            var ot = event.clientY - obj.offsetTop;
            document.onmousemove = function(event){
              event = event || window.event;
              var left = event.clientX - ol;
              var top = event.clientY - ot;
              //修改box1的位置
              obj.style.left = left+"px";
              obj.style.top = top+"px";
            };
            //为document绑定一个鼠标松开事件
            document.onmouseup = function(){
              document.onmousemove = null;
              document.onmouseup = null;
              obj.releaseCapture && obj.releaseCapture();
            };
            return false;

          };
        }
      },
    },

  }
</script>
<style lang="scss" scoped>

</style>
<!--
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})-->


<!--在很多时候，你可能想在 bind 和 update 时触发相同行为，而不关心其它的钩子。比如这样写：

Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value

})-->


<!--bind:绑定时，自定义指令绑定于相应dom时执行（类似于vue生命周期的beforeMount）-->
<!--inserted:指令所在dom添加到父节点时执行，渲染时（类似于以前的mounted）-->
<!--update:更新时，不保证更新完成（指令所在组件有更新时执行），不保证该更新和当前指令所在dom有关-->
<!--componentUpdated:更新完成时，指令所在组件更新完成（类似于以前vue生命周期的updated）-->
<!--unbind:解除绑定，类似于beforeDestroy-->
<style scoped>
  /* 放大的图片，通过定位将左上角定位到(0,0) */
  /*这个放大效果是 图片大小是盒子大小2倍 的视觉效果*/
  .rightImg {
    display: inline-block;
    width: 800px;
    height: 800px;
    position: absolute;
    top: 0;
    left: 0;
  }
  /* 右边的区域 盒子大小 */
  .right {
    margin-left: 412px;
    width: 400px;
    height: 400px;
    border: 1px solid red;
    position: relative;
    overflow: hidden;
  } /* 一个最高层层罩 */
  .maskTop {
    width: 400px;
    height: 400px;
    position: absolute;
    z-index: 1;
    top: 0;
    left: 0;
  } /* 层罩，通过定位将左上角定位到(0,0) */
  .top {
    width: 200px;
    height: 200px;
    background-color: lightcoral;
    opacity: 0.4;
    position: absolute;
    top: 0;
    left: 0;
  } /* 原图的显示 */
  .leftImg {
    width: 400px;
    height: 400px;
    display: inline-block;
  } /* 原图的容器 */
  .left {
    width: 400px;
    height: 400px;
    border: 1px solid teal;
    float: left;
    position: relative;
  }
</style>

